#include <stdafx.h>

#include <kgraphics/math/Vector2.h>
#include <kgraphics/math/math.h>

namespace gfx {

Vector2 Vector2::xAxis( 1.0f, 0.0f );
Vector2 Vector2::yAxis( 0.0f, 1.0f );
Vector2 Vector2::origin( 0.0f, 0.0f );
Vector2 Vector2::xy( 1.0f, 1.0f );

//-------------------------------------------------------------------------------
//-- Methods --------------------------------------------------------------------
//-------------------------------------------------------------------------------

//-------------------------------------------------------------------------------
// @ operator<<()
//-------------------------------------------------------------------------------
// Text output for debugging
//-------------------------------------------------------------------------------
Writer& 
operator<<(Writer& out, const Vector2& source)
{
    out << '<' << source.x << ',' << source.y << ',' << '>';

    return out;
    
}   // End of operator<<()
    

//-------------------------------------------------------------------------------
// @ Vector2::Length()
//-------------------------------------------------------------------------------
// Vector length
//-------------------------------------------------------------------------------
float 
Vector2::Length() const
{
    return Sqrt( x*x + y*y );

}   // End of Vector2::Length()


//-------------------------------------------------------------------------------
// @ Vector2::LengthSquared()
//-------------------------------------------------------------------------------
// Vector length squared (avoids square root)
//-------------------------------------------------------------------------------
float 
Vector2::LengthSquared() const
{
    return (x*x + y*y);

}   // End of Vector2::LengthSquared()


//-------------------------------------------------------------------------------
// @ Vector2::operator==()
//-------------------------------------------------------------------------------
// Comparison operator
//-------------------------------------------------------------------------------
bool 
Vector2::operator==( const Vector2& other ) const
{
    if ( AreEqual( other.x, x )
        && AreEqual( other.y, y ) )
        return true;

    return false;   
}   // End of Vector2::operator==()


//-------------------------------------------------------------------------------
// @ Vector2::operator!=()
//-------------------------------------------------------------------------------
// Comparison operator
//-------------------------------------------------------------------------------
bool 
Vector2::operator!=( const Vector2& other ) const
{
    if ( AreEqual( other.x, x )
        && AreEqual( other.y, y ) )
        return false;

    return true;
}   // End of Vector2::operator!=()


//-------------------------------------------------------------------------------
// @ Vector2::IsZero()
//-------------------------------------------------------------------------------
// Check for zero vector
//-------------------------------------------------------------------------------
bool 
Vector2::IsZero() const
{
    return gfx::IsZero(x*x + y*y);

}   // End of Vector2::IsZero()


//-------------------------------------------------------------------------------
// @ Vector2::Clean()
//-------------------------------------------------------------------------------
// Set elements close to zero equal to zero
//-------------------------------------------------------------------------------
void
Vector2::Clean()
{
    if ( gfx::IsZero( x ) )
        x = 0.0f;
    if ( gfx::IsZero( y ) )
        y = 0.0f;

}   // End of Vector2::Clean()


//-------------------------------------------------------------------------------
// @ Vector2::Normalize()
//-------------------------------------------------------------------------------
// Set to unit vector
//-------------------------------------------------------------------------------
void
Vector2::Normalize()
{
    float lengthsq = x*x + y*y;

    if ( gfx::IsZero( lengthsq ) )
    {
        Zero();
    }
    else
    {
        float factor = InvSqrt( lengthsq );
        x *= factor;
        y *= factor;
    }

}   // End of Vector2::Normalize()


//-------------------------------------------------------------------------------
// @ Vector2::operator+()
//-------------------------------------------------------------------------------
// Add vector to self and return
//-------------------------------------------------------------------------------
Vector2 
Vector2::operator+( const Vector2& other ) const
{
    return Vector2( x + other.x, y + other.y );

}   // End of Vector2::operator+()


//-------------------------------------------------------------------------------
// @ Vector2::operator+=()
//-------------------------------------------------------------------------------
// Add vector to self, store in self
//-------------------------------------------------------------------------------
Vector2& 
operator+=( Vector2& self, const Vector2& other )
{
    self.x += other.x;
    self.y += other.y;

    return self;

}   // End of Vector2::operator+=()


//-------------------------------------------------------------------------------
// @ Vector2::operator-()
//-------------------------------------------------------------------------------
// Subtract vector from self and return
//-------------------------------------------------------------------------------
Vector2 
Vector2::operator-( const Vector2& other ) const
{
    return Vector2( x - other.x, y - other.y );

}   // End of Vector2::operator-()


//-------------------------------------------------------------------------------
// @ Vector2::operator-=()
//-------------------------------------------------------------------------------
// Subtract vector from self, store in self
//-------------------------------------------------------------------------------
Vector2& 
operator-=( Vector2& self, const Vector2& other )
{
    self.x -= other.x;
    self.y -= other.y;

    return self;

}   // End of Vector2::operator-=()

//-------------------------------------------------------------------------------
// @ Vector2::operator-() (unary)
//-------------------------------------------------------------------------------
// Negate self and return
//-------------------------------------------------------------------------------
Vector2
Vector2::operator-() const
{
    return Vector2(-x, -y);
}    // End of Vector2::operator-()


//-------------------------------------------------------------------------------
// @ operator*()
//-------------------------------------------------------------------------------
// Scalar multiplication
//-------------------------------------------------------------------------------
Vector2   
Vector2::operator*( float scalar )
{
    return Vector2( scalar*x, scalar*y );

}   // End of operator*()


//-------------------------------------------------------------------------------
// @ operator*()
//-------------------------------------------------------------------------------
// Scalar multiplication
//-------------------------------------------------------------------------------
Vector2   
operator*( float scalar, const Vector2& vector )
{
    return Vector2( scalar*vector.x, scalar*vector.y );

}   // End of operator*()


//-------------------------------------------------------------------------------
// @ Vector2::operator*()
//-------------------------------------------------------------------------------
// Scalar multiplication by self
//-------------------------------------------------------------------------------
Vector2&
Vector2::operator*=( float scalar )
{
    x *= scalar;
    y *= scalar;

    return *this;

}   // End of Vector2::operator*=()


//-------------------------------------------------------------------------------
// @ operator/()
//-------------------------------------------------------------------------------
// Scalar division
//-------------------------------------------------------------------------------
Vector2   
Vector2::operator/( float scalar )
{
    return Vector2( x/scalar, y/scalar );

}   // End of operator/()


//-------------------------------------------------------------------------------
// @ Vector2::operator/=()
//-------------------------------------------------------------------------------
// Scalar division by self
//-------------------------------------------------------------------------------
Vector2&
Vector2::operator/=( float scalar )
{
    x /= scalar;
    y /= scalar;

    return *this;

}   // End of Vector2::operator/=()


//-------------------------------------------------------------------------------
// @ Vector2::Dot()
//-------------------------------------------------------------------------------
// Dot product by self
//-------------------------------------------------------------------------------
float               
Vector2::Dot( const Vector2& vector ) const
{
    return (x*vector.x + y*vector.y);

}   // End of Vector2::Dot()


//-------------------------------------------------------------------------------
// @ Dot()
//-------------------------------------------------------------------------------
// Dot product friend operator
//-------------------------------------------------------------------------------
float               
Dot( const Vector2& vector1, const Vector2& vector2 )
{
    return (vector1.x*vector2.x + vector1.y*vector2.y);

}   // End of Dot()


//-------------------------------------------------------------------------------
// @ Vector2::PerpDot()
//-------------------------------------------------------------------------------
// Perpendicular dot product by self
//-------------------------------------------------------------------------------
float               
Vector2::PerpDot( const Vector2& vector ) const
{
    return (x*vector.y - y*vector.x);

}   // End of Vector2::Dot()


//-------------------------------------------------------------------------------
// @ Dot()
//-------------------------------------------------------------------------------
// Dot product friend operator
//-------------------------------------------------------------------------------
float               
PerpDot( const Vector2& vector1, const Vector2& vector2 )
{
    return (vector1.x*vector2.y - vector1.y*vector2.x);

}   // End of Dot()




Vector2& Vector2::RotationPos(float dir, float rad)
{
	x = x + (rad * sin(dir));
	y = y - (rad * cos(dir));

	return *this;
}


} // namespace gfx
